package svc.elib.analysis;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;

import svc.elib.db.Author;
import svc.elib.db.Database;
import svc.elib.db.Paper;
import svc.elib.socnet.Net;
import svc.elib.socnet.SocConstructor;

/**
 * Evolution of eLibrary
 * 
 * @author svc
 * @date 9.6.2012
 */
public class ElibEvolution {

	private Database db = null;
	
	private Net net = null;
	
	private int startYear;
	
	private int endYear;
	
	public ElibEvolution() 
		throws IOException
	{
		startYear = 1932;
		endYear = 2011;
		db = new Database("eLibData.csv", 1932, 2011);
		System.out.println(db.info());
		SocConstructor soc = new SocConstructor(db);
		net = soc.getNet();
		net.printInfo();
	}
	
	
	/**
	 * Calculates
	 *    1. number of papers per year
	 *    2. number of authors per year
	 *    3. number of male authors per year
	 *    4. number of female authors per year
	 *    5. average number of authors per paper per year
	 *    6. average number of male authors per paper per year
	 *    7. average number of female authors per paper per year
	 * @param outFile
	 * @throws IOException
	 */
	public void statisticsPerYear(String outFile) 
		throws IOException
	{
		int numSteps = endYear - startYear + 1;
		
		int[] numPapers = new int[numSteps]; 
		int[] numSingleAuthorPapers = new int[numSteps];
		int[] total = new int[numSteps];
		int[] totalMale = new int[numSteps];
		int[] totalFemale = new int[numSteps];
		
		HashMap<Integer, HashSet<Author>> authorsPerYear = 
			new HashMap<Integer, HashSet<Author>>();
		
		HashMap<Integer, HashSet<Author>> malePerYear = 
			new HashMap<Integer, HashSet<Author>>();
		
		HashMap<Integer, HashSet<Author>> femalePerYear = 
			new HashMap<Integer, HashSet<Author>>();
		
		LinkedList<Paper> papers = db.getPapers();
		
		for (int i = 0; i < papers.size(); i++) {
			Paper p = papers.get(i);
			int year = p.getYear();
			int index = year - startYear;
			
			numPapers[index]++;
			
			LinkedList<Author> authors = p.getAuthors();
			total[index] += authors.size();
			
			if (authors.size() == 0) {
				System.out.println("Nesto ne stima");
			}
			
			if (authors.size() == 1) {
				numSingleAuthorPapers[index]++;
			}
			
			for (int j = 0; j < authors.size(); j++) {
				Author a = authors.get(j);
				updateIndex(authorsPerYear, a, year);
				if (a.isMale()) {
					totalMale[index]++;
					updateIndex(malePerYear, a, year);
				}
				else {
					totalFemale[index]++;
					updateIndex(femalePerYear, a, year);
				}
			}
		}
		
		String header = "Year,NumPapersPerYear,NumAuthorsPerYear,NumMaleAuthors,NumFemaleAuthors,AverageNumberOfAuthorsPerPaper, AverageNumberOfMaleAuthors, AverageNumberOfFemaleAuthors, fOneAuthorPapers"; 
		PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(outFile)));
		pw.println(header);
		System.out.println(header);
		for (int i = 0; i < total.length; i++) {
			int year = i + startYear;
			int np = numPapers[i];
			
			int na = 0;
			HashSet<Author> apy = authorsPerYear.get(year);
			if (apy != null)
				na = apy.size();
			
			int nma = 0;
			HashSet<Author> mapy = malePerYear.get(year);
			if (mapy != null)
				nma = mapy.size();
			
			int nfa = 0;
			HashSet<Author> fapy = femalePerYear.get(year);
			if (fapy != null)
				nfa = fapy.size();
			
			double avg = (double) total[i] / (double) numPapers[i];
			double avgMale = (double) totalMale[i] / (double) numPapers[i];
			double avgFemale = (double) totalFemale[i] / (double) numPapers[i];
			
			double fIsolated = (double) numSingleAuthorPapers[i] / (double) numPapers[i];
			
			if (numPapers[i] == 0) {
				avg = 0;
				avgMale = 0;
				avgFemale = 0;
			}
			
			StringBuilder sb = new StringBuilder();
			sb.append(year).append(",")
			  .append(np).append(",")
			  .append(na).append(",")
			  .append(nma).append(",")
			  .append(nfa).append(",")
			  .append(avg).append(",")
			  .append(avgMale).append(",")
			  .append(avgFemale).append(",")
			  .append(fIsolated);
			
			pw.println(sb.toString());
			System.out.println(sb.toString());
		}
		
		pw.close();
	}
	
	private void updateIndex(HashMap<Integer, HashSet<Author>> map, Author a, int year) {
		HashSet<Author> vals = map.get(year);
		if (vals == null) {
			vals = new HashSet<Author>();
			vals.add(a);
			map.put(year, vals);
		} else {
			vals.add(a);
		}
	}
	
	public static void main(String[] args) 
		throws IOException
	{
		ElibEvolution ee = new ElibEvolution();
		ee.statisticsPerYear("results/Elib_StatisticsPerYear.csv");
	}
}